package com.sky.aop;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.sky.anotion.StatusConvert;
import com.sky.enumeration.StatusDescriptionManager;
import com.sky.result.Result;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.lang.reflect.Field;
import java.util.*;

/**
 * 状态码转换切面
 * 在Controller方法返回前自动为带有@StatusConvert注解的字段添加对应的中文描述
 */
@Aspect
@Component
@Slf4j
public class StatusConvertAspect {

    private final ObjectMapper objectMapper = new ObjectMapper();

    /**
     * 初始化ObjectMapper，支持Java 8时间类型
     */
    @PostConstruct
    public void init() {
        // 注册Java 8时间模块
        objectMapper.registerModule(new JavaTimeModule());
        // 禁用将日期写为时间戳
        objectMapper.disable(com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    }

    /**
     * 切入点：拦截所有Controller的方法
     */
    @Around("execution(* com.sky.controller.*.*(..))")
    public Object convertStatus(ProceedingJoinPoint joinPoint) throws Throwable {
        // 执行原方法
        Object result = joinPoint.proceed();

        // 如果返回结果是Result类型，处理其中的data
        if (result instanceof Result) {
            Result<?> resultObj = (Result<?>) result;
            Object data = resultObj.getData();

            if (data != null) {
                // 将处理后的数据重新设置到Result中
                Object processedData = processStatusConversion(data);
                return Result.success(processedData);
            }
        }

        return result;
    }

    /**
     * 处理状态转换，返回处理后的数据
     */
    private Object processStatusConversion(Object obj) {
        if (obj == null) {
            return null;
        }

        try {
            // 如果是集合，遍历处理每个元素
            if (obj instanceof Collection) {
                Collection<?> collection = (Collection<?>) obj;
                List<Object> processedList = new ArrayList<>();
                for (Object item : collection) {
                    processedList.add(convertObjectToMap(item));
                }
                return processedList;
            } else {
                // 处理单个对象
                return convertObjectToMap(obj);
            }
        } catch (Exception e) {
            log.error("状态转换处理失败", e);
            return obj; // 出错时返回原对象
        }
    }

    /**
     * 将对象转换为Map，并添加状态描述字段
     */
    private Object convertObjectToMap(Object obj) throws Exception {
        if (obj == null) {
            return null;
        }

        // 检查对象是否有需要转换的字段（检查当前对象的类，而不是原始类）
        Class<?> actualClass = obj.getClass();
        if (!hasStatusConvertAnnotation(actualClass)) {
            return obj; // 如果没有需要转换的字段，直接返回原对象
        }

        // 将对象转换为Map
        Map<String, Object> resultMap = objectMapper.convertValue(obj, Map.class);

        // 获取当前对象实际类的所有字段（这样可以处理VO类的注解）
        Field[] fields = getAllFields(actualClass);

        // 查找带有@StatusConvert注解的字段
        for (Field field : fields) {
            StatusConvert annotation = field.getAnnotation(StatusConvert.class);
            if (annotation != null) {
                field.setAccessible(true);

                // 从Map中获取字段值（因为对象可能是从其他对象拷贝而来）
                String fieldName = field.getName();
                Object value = resultMap.get(fieldName);

                // 如果Map中没有值，尝试从原对象获取
                if (value == null) {
                    try {
                        value = field.get(obj);
                    } catch (Exception e) {
                        // 忽略获取失败的情况
                        continue;
                    }
                }

                if (value instanceof Integer) {
                    Integer statusCode = (Integer) value;
                    String description = StatusDescriptionManager.getDescription(
                        annotation.statusType(), statusCode);

                    // 确定目标字段名
                    String targetFieldName = annotation.targetField().isEmpty()
                        ? field.getName() + "_name"
                        : annotation.targetField();

                    // 添加状态描述字段到Map中
                    resultMap.put(targetFieldName, description);

                    log.debug("为字段 {} 添加状态描述: {} -> {}", field.getName(), statusCode, description);
                }
            }
        }

        return resultMap;
    }

    /**
     * 检查类是否有StatusConvert注解的字段
     */
    private boolean hasStatusConvertAnnotation(Class<?> clazz) {
        Field[] fields = getAllFields(clazz);
        for (Field field : fields) {
            if (field.getAnnotation(StatusConvert.class) != null) {
                return true;
            }
        }
        return false;
    }

    /**
     * 获取类及其父类的所有字段
     */
    private Field[] getAllFields(Class<?> clazz) {
        List<Field> fields = new ArrayList<>();

        // 获取当前类的字段
        fields.addAll(Arrays.asList(clazz.getDeclaredFields()));

        // 获取父类的字段
        Class<?> superClass = clazz.getSuperclass();
        while (superClass != null && !superClass.equals(Object.class)) {
            fields.addAll(Arrays.asList(superClass.getDeclaredFields()));
            superClass = superClass.getSuperclass();
        }

        return fields.toArray(new Field[0]);
    }
}
